package com.other.login

import android.app.Activity
import android.os.Build
import androidx.credentials.ClearCredentialStateRequest
import androidx.credentials.CredentialManager
import androidx.credentials.GetCredentialRequest
import androidx.credentials.exceptions.GetCredentialCancellationException
import com.blankj.utilcode.util.MetaDataUtils
import com.google.android.libraries.identity.googleid.GetGoogleIdOption
import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential
import com.libcommon.ext.sGlobalMainScope
import com.other.login.entity.LoginResultEntity
import kotlinx.coroutines.launch
import java.security.MessageDigest
import java.util.UUID


/**
 * Created on 2022/9/8.
 * @author Joker
 * Des: google登陆管理工具
 */
object GoogleLoginManager {

    private val clientId by lazy {
        MetaDataUtils.getMetaDataInApp("google_client_id")
    }

    private val hashedNonce by lazy {
        val rawNonce = UUID.randomUUID().toString()
        val bytes = rawNonce.toByteArray()
        val md = MessageDigest.getInstance("SHA-256")
        val digest = md.digest(bytes)
        digest.fold("") { str, it -> str + "%02x".format(it) }
    }

    private val googleIdOption by lazy {
        GetGoogleIdOption.Builder()
            .setFilterByAuthorizedAccounts(false)
            .setServerClientId(clientId)
            .setAutoSelectEnabled(true)
            .setNonce(hashedNonce)
            .build()
    }

    private var credentialManager: CredentialManager? = null

    /**
     * 初始化google凭证
     */
    fun init(activity: Activity?) {
        if (activity == null) return
        runCatching {
            credentialManager = CredentialManager.create(activity)
        }
        sGlobalMainScope.launch {
            runCatching {
                //预加载初始化
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
                    val requestLogin = GetCredentialRequest.Builder()
                        .addCredentialOption(googleIdOption)
                        .build()
                    credentialManager?.prepareGetCredential(requestLogin)
                }
            }
        }
    }

    /**
     * 开始登陆
     */
    fun startLogin(activity: Activity?, loginResult: (LoginResultEntity) -> Unit) {
        if (activity == null) return
        if (credentialManager == null) {
            OldGoogleLoginManager.startLogin(activity, OldGoogleLoginManager.REQUEST_CODE_ERROR_DIALOG)
            loginResult.invoke(LoginResultEntity(LoginResultEntity.CODE_IGNORE, "ignore", LoginResultEntity.LOGIN_TYPE_GOOGLE))
            return
        }

        val requestLogin = GetCredentialRequest.Builder()
            .addCredentialOption(googleIdOption)
            .build()

        sGlobalMainScope.launch {
            runCatching {
                //开始登录
                val reqResult = credentialManager?.getCredential(request = requestLogin, context = activity)
                reqResult?.credential?.let {
                    val loginData = GoogleIdTokenCredential.createFrom(it.data)
                    loginResult.invoke(
                        LoginResultEntity(
                            LoginResultEntity.CODE_SUCCESS,
                            "google login success",
                            LoginResultEntity.LOGIN_TYPE_GOOGLE,
                            third_token = loginData.idToken,
                            third_id = loginData.id,
                            loginname = loginData.displayName,
                            avatar = loginData.profilePictureUri?.path
                        )
                    )
                }
            }.onFailure {
                it.printStackTrace()
                if (it is GetCredentialCancellationException) {
                    loginResult.invoke(LoginResultEntity(LoginResultEntity.CODE_CANCEL, "${it.message}", LoginResultEntity.LOGIN_TYPE_GOOGLE))
                } else {
                    OldGoogleLoginManager.startLogin(activity, OldGoogleLoginManager.REQUEST_CODE_ERROR_DIALOG)
                    loginResult.invoke(LoginResultEntity(LoginResultEntity.CODE_IGNORE, "${it.message}", LoginResultEntity.LOGIN_TYPE_GOOGLE))
                }
            }
        }
    }

    fun loginOut() {
        sGlobalMainScope.launch {
            val requestLoginOut = ClearCredentialStateRequest()
            credentialManager?.clearCredentialState(requestLoginOut)
        }
    }

    fun onRelease() {
        credentialManager = null
    }
}